<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <!-- 
    侦听器 Watch
      概念：
        监听某个数据，当其发生变化时，去做一些别的事情（任意事情，调用接口、操作DOM、等等）


   -->
    <div id="app">
      <button @click="fn1">演示 flush sync 的问题</button>
      <hr />
      <button @click="msg += '~'">{{ msg }}</button>

      <button id="myCount" @click="count++">{{ count }}</button>

      <button @click="person = {name: '里斯'}">{{ person }}</button>
      <button @click="person.name += '~'">{{ person.name }}</button>
      <button @click="person.city.name += '~'">{{ person.city.name }}</button>
    </div>

    <script type="module">
      import { createApp } from "./lib/vue3.esm.browser.js";

      createApp({
        data() {
          return {
            msg: "hello",
            count: 1,
            person: {
              name: "张三",
              age: 18,
              city: {
                name: "深圳",
              },
            },
          };
        },

        watch: {
          // 语法一：函数语法
          //    key - 要监听的数据
          //    value - 一个 hander 函数，
          //          两个参数：
          //                newVal - 新值
          //                oldVal - 旧值
          //          触发时机：
          //                监听的数据发生变化时触发，初始化时不会触发
          //
          msg(newVal, oldVal) {
            console.log(`msg 改变了 newVal: ${newVal}, oldVal: ${oldVal}`);
          },

          /**
           * 语法二： 对象语法
           *    key - 要监听的数据
           *    value - 一个必须包含有 handler 属性的对象
           *          handler     处理函数
           *          immediate   控制是否默认触发一个 handler, 接受一个 布尔值
           *          deep        控制是否启用深度监听，接受一个 布尔值
           *          flush       控制 handler 的触发时机
           *                      'pre'  真实DOM修改之前 【默认】
           *                      'post' 真实DOM修改之后
           *                      'sync' 慎用，基本不用，让 handler 的时机变成同步。会有性能影响
           *
           */
          count: {
            handler(newVal, oldVal) {
              console.log(`count 改变了 newVal: ${newVal}, oldVal: ${oldVal}`);

              console.log(document.querySelector("#myCount").innerHTML);
            },
            flush: "sync", // 让 handler 不等待了，发生变化即可执行 handler
            // flush: "post", // 让 handler 在真实DOM更新之后再触发
            // immediate: true, // 让 handler 默认触发一次
          },


          /**
           * 使用 . 语法，具体监听一个对象的某个属性
           */ 
          'person.name': {
            handler() {
              console.log('perons.name 改变了')
            }
          }

          // person: {
          //   /**
          //    * 监听一个对象，必须是对象重新赋值才会被触发。
          //    * 对该对象的属性做修改是不会触发该 handler 的。
          //    * 如果需要监空属性的变化，则可以启用深度监听
          //    */
          //   handler() {
          //     console.log("person 改变了");
          //   },
          //   deep: true, // 启用深度监听
          // },
        },

        methods: {
          fn1() {
            // 如下代码会引起 count 监听的 handler 触发几次的问题
            //    1. 没有设置 flush: "sync"       1次
            //    2. 设置了  flush: 'sync'        3次

            // 如下代码会引起 updated 钩子触发几次    【1次】
            //    如果多次的话，则性能太差，内部会将数据的修改当成一个任务
            this.count++;
            this.count++;
            this.count++;
          },
        },

        updated() {
          console.log("updated");
        },
      }).mount("#app");
    </script>
  </body>
</html>
